package com.github.itdachen.service.impl;

import com.github.itdachen.config.DevCodeAppProperties;
import com.github.itdachen.constants.PackageNameConstant;
import com.github.itdachen.constants.UiStyleConstant;
import com.github.itdachen.convert.DevTableColumnConvert;
import com.github.itdachen.entity.DevTableColumn;
import com.github.itdachen.entity.ProtoTable;
import com.github.itdachen.entity.ProtoTableInfo;
import com.github.itdachen.framework.context.BizContextHandler;
import com.github.itdachen.framework.context.exception.BizException;
import com.github.itdachen.framework.core.utils.StringUtils;
import com.github.itdachen.mapper.IDevTableColumnMapper;
import com.github.itdachen.sdk.dto.DevTableColumnDTO;
import com.github.itdachen.sdk.query.ProtoTableQuery;
import com.github.itdachen.sdk.vo.DevTableColumnVO;
import com.github.itdachen.utils.*;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.itdachen.convert.DevTableInfoConvert;
import com.github.itdachen.entity.DevTableInfo;
import com.github.itdachen.mapper.IDevTableInfoMapper;
import com.github.itdachen.service.IDevTableInfoService;
import com.github.itdachen.sdk.dto.DevTableInfoDTO;
import com.github.itdachen.sdk.query.DevTableInfoQuery;
import com.github.itdachen.sdk.vo.DevTableInfoVO;
import com.github.itdachen.framework.core.response.TableData;
import jakarta.servlet.http.HttpServletResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.swing.table.TableColumn;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/**
 * 代码生成业务表 serverImpl
 *
 * @author 王大宸
 * @date 2023-09-23 21:25:55
 */
@Service
public class DevTableInfoServiceImpl implements IDevTableInfoService {
    private static final Logger logger = LoggerFactory.getLogger(DevTableInfoServiceImpl.class);


    @Value("${pagehelper.helperDialect:mysql}")
    private String dbType;

    private final IDevTableInfoMapper devTableInfoMapper;
    private final IDevTableColumnMapper devTableColumnMapper;
    private final DevCodeAppProperties devCodeAppProperties;

    public DevTableInfoServiceImpl(IDevTableInfoMapper devTableInfoMapper, IDevTableColumnMapper devTableColumnMapper, DevCodeAppProperties devCodeAppProperties) {
        this.devTableInfoMapper = devTableInfoMapper;
        this.devTableColumnMapper = devTableColumnMapper;
        this.devCodeAppProperties = devCodeAppProperties;
    }

    /***
     * 分页
     *
     * @author 王大宸
     * @date 2023-09-23 21:25:55
     * @param params 查询参数
     * @return com.github.itdachen.framework.core.response.TableData<com.github.itdachen.sdk.vo.DevTableInfoVo>
     */
    @Override
    public TableData<DevTableInfoVO> findDevTableInfoPage(DevTableInfoQuery params) throws Exception {
        Page<DevTableInfoVO> page = PageHelper.startPage(params.getPage(), params.getLimit());
        if ("MYSQL".equals(dbType.toUpperCase())) {
            List<DevTableInfoVO> list = devTableInfoMapper.findDevTableInfoPage(params);
            return new TableData<DevTableInfoVO>(page.getTotal(), list);
        }
        return new TableData<DevTableInfoVO>(0, new ArrayList<>());
    }

    /***
     * 查询数据库中的表
     *
     * @author 王大宸
     * @date 2023/4/11 21:05
     * @param query query
     * @return com.github.itdachen.framework.core.response.TableData<com.github.itdachen.framework.code.entity.ProtoTable>
     */
    @Override
    public TableData<ProtoTable> findProtoList(ProtoTableQuery query) throws BizException {
        Page<ProtoTable> page = PageHelper.startPage(query.getPage(), query.getLimit());
        if ("MYSQL".equals(dbType.toUpperCase())) {
            List<ProtoTable> list = devTableInfoMapper.findProtoList(query);
            return new TableData<ProtoTable>(page.getTotal(), list);
        }
        return new TableData<ProtoTable>(0, new ArrayList<>());
    }

    /***
     * 导入表
     *
     * @author 王大宸
     * @date 2023/9/23 22:44
     * @param tableNames tableNames
     * @return com.github.itdachen.sdk.vo.DevTableInfoVO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importTableInfo(String tableNames) throws BizException {
        if (null == tableNames) {
            throw new BizException("请选择表");
        }
        List<String> strings = new ArrayList<>(Arrays.asList(tableNames.split(",")));
        if (strings.isEmpty()) {
            throw new BizException("请选择表");
        }
        List<ProtoTable> tableList = devTableInfoMapper.findProtoTableList(strings);
        if (null == tableList || tableList.isEmpty()) {
            throw new BizException("该表不存在");
        }

        for (ProtoTable protoTable : tableList) {
            protoTable.setColumns(devTableInfoMapper.findProtoTableColumns(protoTable.getTableName()));
        }
        String clientId = "", uiStyle = "", menuId = "";
        ProtoTableInfo protoTableInfo = TableColumnFieldUtils.pottingTableInfo(tableList, clientId, uiStyle, menuId);
        if (!protoTableInfo.getTableInfos().isEmpty()) {
            devTableInfoMapper.batchSave(protoTableInfo.getTableInfos());
        }
        if (!protoTableInfo.getTableColumns().isEmpty()) {
            devTableColumnMapper.batchSave(protoTableInfo.getTableColumns());
        }
    }


    @Override
    public void saveImpTableInfo(List<ProtoTable> tableList) throws Exception {
        ProtoTableInfo protoTableInfo = TableColumnFieldUtils.pottingTableInfo(tableList, devCodeAppProperties.getAppId(), UiStyleConstant.LAY_UI, devCodeAppProperties.getMenuId());
        if (!protoTableInfo.getTableInfos().isEmpty()) {
            devTableInfoMapper.batchSave(protoTableInfo.getTableInfos());
        }
        if (!protoTableInfo.getTableColumns().isEmpty()) {
            devTableColumnMapper.batchSave(protoTableInfo.getTableColumns());
        }
    }

    /***
     * 新增
     *
     * @author 王大宸
     * @date 2023-09-23 21:25:55
     * @param devTableInfoDTO 新增数据
     * @return com.github.itdachen.sdk.vo.devTableInfoVO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public DevTableInfoVO saveDevTableInfo(DevTableInfoDTO devTableInfoDTO) throws Exception {
        DevTableInfo devTableInfo = DevTableInfoConvert.toJavaObject(devTableInfoDTO);
        devTableInfo.setId(VelocityContextUtils.getId());
        devTableInfo.setCreateTime(LocalDateTime.now());
        devTableInfo.setCreateUser(BizContextHandler.getNickName());
        devTableInfo.setCreateUserId(BizContextHandler.getUserId());
        devTableInfo.setUpdateTime(LocalDateTime.now());
        devTableInfo.setUpdateUser(BizContextHandler.getNickName());
        devTableInfo.setUpdateUserId(BizContextHandler.getUserId());

        devTableInfoMapper.saveDevTableInfo(devTableInfo);
        return DevTableInfoConvert.toJavaObjectVO(devTableInfo);
    }

    /***
     * 根据id查询
     *
     * @author 王大宸
     * @date 2023-09-23 21:25:55
     * @param id 需要查询数据的id
     * @return com.github.itdachen.sdk.vo.DevTableInfoVO
     */
    @Override
    public DevTableInfoVO getDevTableInfoById(String id) throws Exception {
        return devTableInfoMapper.findTableInfo(id);
    }

    /***
     * 修改
     *
     * @author 王大宸
     * @date 2023-09-23 21:25:55
     * @param devTableInfoDTO 更新数据
     * @return com.github.itdachen.sdk.vo.devTableInfoVO
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public DevTableInfoVO updateDevTableInfo(DevTableInfoDTO devTableInfoDTO) throws Exception {
        DevTableInfo devTableInfo = DevTableInfoConvert.toJavaObject(devTableInfoDTO);

        String conUri = conUriHandler(devTableInfo);
        devTableInfo.setRearUri(conUri);

        String askUri = askUriHandler(devTableInfo);
        devTableInfo.setAskUri(askUri);

        /* 前端包路径处理 */
        String frontPackage = devTableInfo.getFrontPackage();
        if (frontPackage.startsWith("/")) {
            devTableInfo.setFrontPackage(frontPackage.substring(1));
        }

        devTableInfo.setUpdateTime(LocalDateTime.now());
        devTableInfo.setUpdateUser(BizContextHandler.getNickName());
        devTableInfo.setUpdateUserId(BizContextHandler.getUserId());
        devTableInfoMapper.updateDevTableInfo(devTableInfo);

        List<DevTableColumnDTO> columns = devTableInfoDTO.getColumns();
        DevTableColumn tableColumn;
        List<DevTableColumn> list = new ArrayList<>();
        for (DevTableColumnDTO columnDTO : columns) {
            tableColumn = DevTableColumnConvert.toJavaObject(columnDTO);
            tableColumn.setId(columnDTO.getColumnId());
            list.add(tableColumn);
        }


        if (null != list && !list.isEmpty()) {
            for (DevTableColumn devTableColumn : list) {
                devTableColumnMapper.updateDevTableColumn(devTableColumn);
            }
        }

        // devTableColumnMapper.batchUpdate(list);

        return DevTableInfoConvert.toJavaObjectVO(devTableInfo);
    }

    /***
     * 删除
     *
     * @author 王大宸
     * @date 2023-09-23 21:25:55
     * @param id 需要删除数据的id
     * @return int 影响行数
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int removeDevTableInfo(String id) throws Exception {
        devTableColumnMapper.deleteDevTableColumnByTable(id);
        return devTableInfoMapper.deleteDevTableInfoById(id);
    }

    /***
     * 生成代码
     *
     * @author 王大宸
     * @date 2023/10/2 15:57
     * @param tableNames tableNames
     * @param response response
     * @return void
     */
    @Override
    public void downloadCode(String[] tableNames, HttpServletResponse response) throws Exception {
        List<DevTableInfoVO> list = new ArrayList<>();
        for (String tableName : tableNames) {
            list.add(devTableInfoMapper.findUsableTableInfoVoById(tableName));
        }
        CodeHelper.downloadCode(list, response);
    }

    /***
     * 预览代码
     *
     * @author 王大宸
     * @date 2022/8/16 23:20
     * @param id id
     * @return java.util.Map<java.lang.String, java.lang.String>
     */
    @Override
    public Map<String, String> previewCode(String id) throws Exception {
        DevTableInfoVO tableInfoVo = devTableInfoMapper.findUsableTableInfoVoById(id);
        return CodeHelper.previewCode(tableInfoVo);
    }

    /***
     * 添加字段
     *
     * @author 王大宸
     * @date 2023/11/15 17:16
     * @param devTableColumnDTO devTableColumnDTO
     * @return javax.swing.table.TableColumn
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public DevTableColumnVO saveTableColumn(DevTableColumnDTO devTableColumnDTO) throws Exception {
        DevTableColumn javaObject = DevTableColumnConvert.toJavaObject(devTableColumnDTO);
        javaObject.setId(VelocityContextUtils.getId());
        javaObject.setCreateTime(LocalDateTime.now());
        javaObject.setCreateUser(BizContextHandler.getNickName());
        javaObject.setCreateUserId(BizContextHandler.getUserId());
        javaObject.setUpdateTime(LocalDateTime.now());
        javaObject.setUpdateUser(BizContextHandler.getNickName());
        javaObject.setUpdateUserId(BizContextHandler.getUserId());

        /* 添加排序 */
        Integer columnCount = devTableColumnMapper.findColumnCount(javaObject.getTableId());
        if (null == columnCount) {
            columnCount = 0;
        }
        javaObject.setSort(columnCount + 1);

        devTableColumnMapper.saveDevTableColumn(javaObject);
        return DevTableColumnConvert.toJavaObjectVO(javaObject);
    }


    /***
     * controller 访问地址处理
     *
     * @author 王大宸
     * @date 2024/9/2 11:18
     * @param devTableInfo devTableInfo
     * @return java.lang.String
     */
    private String conUriHandler(DevTableInfo devTableInfo) {
        String conUri = devTableInfo.getRearUri();
        if (!conUri.startsWith("/")) {
            conUri = "/" + conUri.replaceAll("//", "");
        }
        if (StringUtils.isEmpty(devTableInfo.getModuleName()) || "/".equals(devTableInfo.getModuleName())) {
            return conUri;
        }
        String module = "/" + devTableInfo.getModuleName();
        if (conUri.startsWith(module)) {
            return conUri;
        }
        conUri = module + conUri;
        return conUri.replaceAll("//", "");
    }

    /***
     * 最终访问地址处理
     *
     * @author 王大宸
     * @date 2024/9/2 11:09
     * @param devTableInfo devTableInfo
     * @return java.lang.String
     */
    private String askUriHandler(DevTableInfo devTableInfo) {
        String askUri = devTableInfo.getRearUri();
        if (StringUtils.isEmpty(devTableInfo.getContextPath()) || "/".equals(devTableInfo.getContextPath())) {
            return askUri;
        }
        String contextPath = devTableInfo.getContextPath();
        if (!contextPath.startsWith("/")) {
            contextPath = "/" + contextPath;
        }
        if (askUri.startsWith(contextPath)) {
            return askUri;
        }
        if (StringUtils.isEmpty(contextPath)) {
            return askUri;
        }
        contextPath = contextPath.replaceAll("//", "/");
        if (contextPath.startsWith("/")) {
            askUri = contextPath + askUri;
        } else {
            askUri = contextPath + askUri;
        }
        return askUri.replaceAll("//", "/");
    }


}
